#pragma once

#include <map>
using std::map;
template <typename ClassIDType, typename ClassType>

class CObjectFactory
{
private:
	typedef ClassType* (*TheCreator)(void);
	map<ClassIDType, TheCreator> m_CreatorsMap;
	static CObjectFactory<ClassIDType, ClassType> s_Instance;
	CObjectFactory() {}
	CObjectFactory(const CObjectFactory&);
	CObjectFactory& operator=(const CObjectFactory&);
	~CObjectFactory(void) {};
	template<typename DerivedClass>
	static ClassType* ConstructObject()
	{
		return new DerivedClass;
	}
public:
	static CObjectFactory<ClassIDType, ClassType>* GetInstance()
	{
		return &s_Instance;
	}
	void ShutDownObjectFactoy()
	{
		m_CreatorsMap.clear();
	}
	template<typename DerivedClass>
	bool RegisterClassType(ClassIDType id)
	{
		std::pair<ClassIDType, TheCreator> objType;
		objType.first = id;
		objType.second = ConstructObject<DerivedClass>;
		m_CreatorsMap.insert(objType);
		return true;
	}
	bool UnrigisterClassType(ClassIDType id)
	{
		map<ClassIDType, TheCreator>::iterator ite = m_CreatorsMap.find(id);
		if(ite == m_CreatorsMap.end())
			return false;
		m_CreatorsMap.erase(ite);
		return true;
	}
	ClassType* CreateObject(ClassIDType id)
	{
		map<ClassIDType, TheCreator>::iterator ite = m_CreatorsMap.find(id);
		if(ite == m_CreatorsMap.end())
			return NULL;
		return (*ite).second();
	}
};

template<typename ClassIDType, typename ClassType>
CObjectFactory<ClassIDType,ClassType>
CObjectFactory<ClassIDType,ClassType>::s_Instance;